package com.imyuanma.qingyun.common.config.security;

import com.imyuanma.qingyun.common.exception.Exceptions;
import com.imyuanma.qingyun.common.util.encript.MD5Util;
import com.imyuanma.qingyun.common.util.encript.RSAUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * 默认的加密实现
 *
 * @author wangjy
 * @date 2022/07/09 15:30:12
 */
public class DefaultPasswordEncoder implements PasswordEncoder {
    private static final Logger logger = LoggerFactory.getLogger(DefaultPasswordEncoder.class);
    /**
     * 加密盐
     */
    private String salt;
    public static final String SSO_CLIENT_RSA_KEY_PRIVATE = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJ+brwwCQyYJ9c+Y/P9JLBo6sRCjuXEMpO2bbXOBNGgpjn41N6iD2ulRRukR8po7FHLsrAX+B459xHQBZIEkdCS3r135K5Q5Ei3LSlyEiNQ0ZyVvGP4sJSVnDIIi4aMGTkKSUF2Lg1GhseDHawrhWSf2hlWwFpDTItD704kW9rmJAgMBAAECgYEAh6a1u6sgju/gLzSDsiTqitBfNRkxvtdURW3YNFcXx3+qT7HDQEHwiGQ/tE9AtbyIwLRN8DnbCkvx7/ZPCUOGQWR8FDZ7BLHl9EVJXQ8ffWlCwrT9ZCbOOCpF3yBhpJNG5LCtxt4yrZnX5PibGqcQkP3jW0/+X+uQlvPMFYmMA1ECQQDkhfjI4pxDUaHPU7O6twpMkpyj0Tt0wUFQ4maGFPn2s2PC03mgGxPkuKEaxHL4B7ao5DtWHiJWGCpwMcGCNH/rAkEAssx6cobfOqAk1X8KetHu7YwCQnbyloIjQJ9kg43t2bR2GJcp1bTsLveZf1Ch3ZxpwSO5c4j8qbZ+mEQt9IiDWwJAM7/m887lZhVBWErzI3A549c7o5lJJopw+Rkb8Hcll+lNyRvMqiYXni71RLOB+Yr9oUd17G2MhwSX76pE0PCEmwJAYli2wWgOQWD04boPOZ9fnKn2VDi5FrBeU51Y3EOlIKpyivQavsHVZ8ApXi4r2om+Yc4Uo8glsfP/jiFyZZ7xIQJBAIPqU1Fu8xc4+xmuc7Ab2+gDQjK58rGMM7ODOlXuPjB7tkPQCWW5TppCX87y8znn0kT/WAKYSD8wxsOYULIipXA=";


    /**
     * 构造实例
     *
     * @param salt
     * @return
     */
    public static DefaultPasswordEncoder newInstance(String salt) {
        return new DefaultPasswordEncoder(salt);
    }

    private DefaultPasswordEncoder(String salt) {
        this.salt = salt;
    }

    /**
     * 加密
     *
     * @param rawPassword 前端入参密码, 注册时使用
     * @return
     */
    @Override
    public String encode(CharSequence rawPassword) {
        logger.info("[默认的加密实现-encode] 输入的密码为:{}", rawPassword);
        return this.encodeStr(rawPassword.toString());
//        return this.encodeStr(this.parseInputPassword(rawPassword));
    }

    private String encodeStr(String str) {
        return MD5Util.MD5(str + salt);
    }

    /**
     * 解析用户真正输入的密码
     *
     * @param rawPassword 前端入参密码, 前端加密过程: 原文 -> base64编码(utf8) -> rsa加密得到密文 -> 对密文base64编码(utf8)
     * @return
     */
    public String parseInputPassword(CharSequence rawPassword) {
        try {
            byte[] bytes = RSAUtil.decryptByPrivate(Base64.getDecoder().decode(rawPassword.toString()), SSO_CLIENT_RSA_KEY_PRIVATE);
            String pwd = new String(Base64.getDecoder().decode(bytes), StandardCharsets.UTF_8);
            logger.info("[解析用户真正输入的密码] 入参密码解密后={}", pwd);
            return pwd;
        } catch (Exception e) {
            logger.error("[解析用户真正输入的密码] 解密时发生异常,入参={}", rawPassword, e);
            throw new PasswordDecodeException("入参密码解密失败");
        }
    }

    /**
     * 密码验证
     *
     * @param rawPassword     前端入参密码
     * @param encodedPassword 数据库存储密码
     * @return
     */
    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        logger.info("[默认的加密实现-matches] 输入的密码为:{},数据库返回的密码为:{}", rawPassword, encodedPassword);
        return this.encodeStr(this.parseInputPassword(rawPassword)).equals(encodedPassword);
    }

    /**
     * 是否加密2次
     *
     * @param encodedPassword 加密一次后的密码
     * @return
     */
    @Override
    public boolean upgradeEncoding(String encodedPassword) {
        return false;
    }
}
